package com.jltx.compiler;

import com.google.auto.service.AutoService;

import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.MirroredTypeException;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;


/**
 * @author aidenquan
 * Created by junlintianxia on 2020/08/26.
 */
@AutoService(Processor.class)
public class MyServiceProcessor extends AbstractProcessor {
    Types typeUtils;
    Elements elementUtils;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        typeUtils = processingEnvironment.getTypeUtils();
        elementUtils = processingEnvironment.getElementUtils();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        //获取所有自定义的MyService注解的类信息
        Set<Element> elementSet = (Set<Element>) roundEnvironment.getElementsAnnotatedWith(MyService.class);
        if (elementSet != null && elementSet.size() > 0) {
            Set<TypeElement> typeElementSet = ElementFilter.typesIn(elementSet);
            for (TypeElement typeElement : typeElementSet) {
                MyService myService = typeElement.getAnnotation(MyService.class);
                //获取注解的的相关信息的映射
                TypeElement interfaceElement = getInterfaceElement(myService);
                if (interfaceElement == null) {
                    error(typeElement, "interfaceElement == null");
                }
                //得到所在类的包名
                String packageName = elementUtils.getPackageOf(interfaceElement).getQualifiedName().toString();
                //打印
                note(typeElement, "packageName:" + packageName);
            }
        }
        return true;
    }

    private TypeElement getInterfaceElement(MyService componentAnnotation) {
        TypeMirror typeMirror = null;
        try {
            componentAnnotation.value();
        } catch (MirroredTypeException e) {
            typeMirror = e.getTypeMirror();
        }

        return typeUtils != null ? (TypeElement) typeUtils.asElement(typeMirror) : null;
    }

    /**
     * 打印日志
     *
     * @param element
     * @param msg
     * @param args
     */
    public void error(Element element, String msg, Object... args) {
        printMessage(Diagnostic.Kind.ERROR, element, msg, args);
    }

    /**
     * 打印日志
     *
     * @param element
     * @param msg
     * @param args
     */
    public void note(Element element, String msg, Object... args) {
        printMessage(Diagnostic.Kind.NOTE, element, msg, args);
    }

    /**
     * 打印日志
     *
     * @param kind
     * @param element
     * @param msg
     * @param args
     */
    public void printMessage(Diagnostic.Kind kind, Element element, String msg, Object... args) {
        String message = msg;
        if (args.length != 0) {
            message = String.format(message, args);
        }

        processingEnv.getMessager().printMessage(kind, message, element);
    }
}
